import axios, { AxiosResponse } from 'axios';
import { message } from 'antd';
import AppResponseCode from './app_response_code';
import AppConstant from '@/services/common/AppConstant';

export interface ServerResponse {
  code: number,
  msg?: string,
  data?: any
}

// 创建 Axios 实例
const http = axios.create({
  // 从umi配置的环境变量中加载
  baseURL: AppConstant.UMI_BASE_URL,
  timeout: 60 * 1000, // 请求超时时间
});

// 请求拦截器
http.interceptors.request.use(
  (config) => {
    // 在请求头中添加 Token
    const token = localStorage.getItem(AppConstant.localStroageTokenKey);
    if (token) {
      config.headers.Authorization = `Bearer ${token}`;
    }
    return config;
  },
  (error) => {
    return Promise.reject(error);
  }
);

// 响应拦截器
http.interceptors.response.use(
  (response: AxiosResponse) => {
    // 处理 2xx 类响应
    if (!response.data) {
      // 服务端应该统一返回AppResponse，相同的数据结构，为空不处理
      return null;
    }
    if (response.headers['content-type'] === 'application/octet-stream') {
      return response;
    }
    const serverResponse = response.data as ServerResponse
    if (serverResponse.code < 200 || serverResponse.code >= 300) {
      if(serverResponse.msg) {message.error(serverResponse.msg) }
      else {message.error("业务处理异常: " + serverResponse.code)}
      return null;
    }
    if (serverResponse.code === AppResponseCode.REFRESH_TOKEN.code) {
      const newAccessToken = response.headers['authorization'];
      localStorage.setItem(AppConstant.localStroageTokenKey, newAccessToken)
    }
    return serverResponse.data
  },
  (error) => {
    // 后端项目规范，请求到的都是200的http响应状态码
    message.error('服务器异常，请稍后重试');
    return Promise.reject(error);
  }
);

// fetch http调用
const requestAuthorizationInterceptor = (url: string, options: any) : {url: string, options: any} => {
  const token = localStorage.getItem(AppConstant.localStroageTokenKey);
  if (token) {
    options.headers = {
      ...options.headers,
      Authorization: 'Bearer ' + token,
    };
  }
  return { url, options };
};

const streamRequestAuthorizationInterceptor = (url: string, options: any) : {url: string, options: any} => {
  const token = localStorage.getItem(AppConstant.localStroageTokenKey);
  if (token) {
    options.headers = {
      ...options.headers,
      Authorization: 'Bearer ' + token,
      [AppConstant.IsStreamRequestHttpHeaderKey]: AppConstant.IsStreamRequestHttpHeaderEnableValue 
    };
  }
  return { url, options };
};

const responseInterceptor = async (response: Response) => {
  if (!response.ok) {
    message.error('无法请求到服务器，请稍后重试');
    return Promise.reject("无法请求到服务器，请稍后重试")
  }
  const serverResponse =  await response.json() as ServerResponse
  if (serverResponse.code < 200 || serverResponse.code >= 300) {
    if(serverResponse.msg) {message.error(serverResponse.msg) }
    else {message.error("业务处理异常: " + serverResponse.code)}
    return Promise.reject("业务处理异常");
  }
  return response;
};

/**
 * 流式请求要求后端接口异常时不能也返回200，需要再响应头中设置http状态码
 */
const streamResponseIntercaptor = async (response: Response) => {
  if (!response.ok) {
    const serverResponse =  await response.json() as ServerResponse
    if(serverResponse.msg) {message.error(serverResponse.msg) }
    else {message.error("业务处理异常: " + serverResponse.code)}
    return Promise.reject("业务处理异常");
  }
  return response;
};
const requestInterceptors = [requestAuthorizationInterceptor]
const responseInterceptors = [responseInterceptor]
const streamRequestInterceptors = [streamRequestAuthorizationInterceptor]
const streamResponseInterceptors = [streamResponseIntercaptor]

const fetchHttp = async (url: string, options: any = {}) => {
  // 执行请求拦截器
  let interceptOptions = { url, options };
  for (const interceptor of requestInterceptors) {
      const result = interceptor(url, options);
      if (result) {
          interceptOptions = result;
      }
  }
  // 执行 fetch 请求
  let response;
  response = await fetch(interceptOptions.url, interceptOptions.options);
  // 执行响应拦截器
  try {
    for (const interceptor of responseInterceptors) {
        response = await interceptor(response);
    }
  } catch(err) {
    console.log(err);
    // 拦截器处理不通过，后续也不用继续处理了
    return null;
  }
  return response;
}

/**
 * 流式请求处理中，如果校验不通过会直接返回body数据，而校验通过则会按照数据块返回
 */
const fetchHttpWithStream = async (url: string, options: any = {}) => {
  // 执行请求拦截器
  let interceptOptions = { url, options };
  for (const interceptor of streamRequestInterceptors) {
      const result = interceptor(url, options);
      if (result) {
          interceptOptions = result;
      }
  }
  // 执行 fetch 请求
  let response;
  response = await fetch(interceptOptions.url, interceptOptions.options);
  // 执行响应拦截器
  try {
    console.log("拦截器触发");
    for (const interceptor of streamResponseInterceptors) {
        response = await interceptor(response);
    }
  } catch(err) {
    console.log(err);
    // 拦截器处理不通过，后续也不用继续处理了
    return null;
  }
  return response;
}

export const AppHttp = {
   fetchHttp,
   fetchHttpWithStream,
   axiosHttp: http
}
export default http;

